#include <stdio.h>
#include <stdlib.h>
#ifdef UMPI
#include <mpi.h>
#endif

#ifdef UOMP
#include <omp.h>
#endif

long int num_steps = 2E10; //
double step;

int main(int argc, char **argv){
    int threads_num = 1;
    if(argc > 1){
        threads_num =  atoi(argv[1]);
    }
    int myid = 0, numprocess = 1;
    double pi = 0.0, sum = 0.0, start = 0.0, end = 0.0;
    step = 1.0 / (double)num_steps;
    #ifdef UMPI
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &myid);
        MPI_Comm_size(MPI_COMM_WORLD, &numprocess);
        start = MPI_Wtime();
    #endif
    #ifdef UOMP
        if(myid == 0) printf("threads_num = %d  ", threads_num);
        omp_set_num_threads(threads_num);
        #pragma omp parallel for reduction(+:sum)
    #endif
    for(long int i = myid + 1; i <= num_steps; i+=numprocess){
        double x = (i - 0.5) * step;
        sum += 4.0 / (1.0 + x * x);
    }
    sum = sum * step;
    #ifdef UMPI
        MPI_Barrier(MPI_COMM_WORLD);
        MPI_Reduce(&sum, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
    #endif


    if(myid == 0)
        printf("pi = %.20lf\n", pi);

    #ifdef UMPI
        end = MPI_Wtime();
        MPI_Finalize();
        if(myid == 0)printf("time = %f\n", end - start);
    #endif

}
